package edu.biwu.sms;



import edu.biwu.sms.enum01.EnrollmentStatus;
import org.junit.Test;

import java.io.*;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.*;

public class StudentManagementSystem02 {

//    private ArrayList<Stduent> students = new ArrayList();
    private  ArrayList<Stduent> students=new ArrayList<>();

    public void setPropertyValue(Stduent student,String propertyName,Object value)throws  Exception{
        Class<?> cls =student.getClass();
        System.out.println(cls);
        Field field = null;
        while (cls!=null) {//如果cls=null，说明已经找到祖宗类
            try {
                field = cls.getDeclaredField(propertyName);//先获取本字码中是否有该属性
                break;
            } catch (NoSuchFieldException e) {
                cls= cls.getSuperclass();
            }
        }

        field.setAccessible(true);
        field.set(student,value);
    }
public Object getPropertyValue(Stduent stduent,String propertyName) throws Exception {
    Class<?> cls = stduent.getClass();
    System.out.println(cls);
    Field field = null;
    while (cls!=null) {//如果cls=null，说明已经找到祖宗类
        try {
            field = cls.getDeclaredField(propertyName);//先获取本字码中是否有该属性
            break;
        } catch (NoSuchFieldException e) {
           cls= cls.getSuperclass();
        }
    }
    //当循环执行完毕会出现两种情况
    //1.找到,field被赋值,通过break中断的循环
    //2.没找到,从当前字节码开始=>找父类的字节码=>...=>一直找到Object类字节码都没找到
    if(field==null){
        throw new NoSuchFieldException("整个继承体系都找不到"+propertyName);
    }
//    跳过java权限
    field.setAccessible(true);
    //3.设置指定的学生对象的属性值
     return field.get(stduent);
}

    public void writeRankedStudentsToFile(String resultPath) throws IOException {
        //1.总分从高到低排名
        sortByTotalScore();
        //2.再将排好序的学生信息写入到resultPath指定文件
      try(  BufferedWriter bw = new BufferedWriter(new FileWriter(resultPath))) {
          for (Stduent student : students) {
              bw.write(String.valueOf(student));
              bw.newLine();
          }
      }
    }
    public  void  loadStudentsFromFile(String filePath) throws IOException {
        //关联指定文件路径 再利用BufferedReader进行包装，为了使用readline()方法
//        File file = new File(filePath);
        //会从测试类的根路径下加载：target/test—classes作为根目录，搜索指定的资源文件
// 获取文件的输入流
        InputStream is = StudentManagementSystem02.class.getResourceAsStream(filePath);


        if (is == null) {
            throw new FileNotFoundException("File not found: " + filePath);
        }

// 利用转化流将字节流转化成字符流，在包装成缓冲流
        try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
       String line;
       while ((line= br.readLine())!=null) {
           String[] data = line.split(",");
           String stuId = data[0];
           String name = data[1];
           double chineseSocre = Double.parseDouble(data[2]);
           double mathSocre = Double.parseDouble(data[3]);
           LocalDate enrollmentDate = LocalDate.parse(data[4]);
           String email = data[5];
           EnrollmentStatus enrollmentStatus = EnrollmentStatus.getEnumByDesc(data[6]);
           if (filePath.equals("中学生信息01.txt")) {
               //封装中学生特有信息：历史成绩和物理成绩
               double historyScore = Double.parseDouble(data[7]);
               double physicsScore = Double.parseDouble(data[8]);
               MiddleStudent middleStudent = new MiddleStudent(stuId, name, chineseSocre, mathSocre,historyScore,physicsScore, enrollmentDate, email,enrollmentStatus);
               students.add(middleStudent);
           } else if (filePath.equals("小学生信息01.txt")) {
               PrimaryStduent primaryStduent = new PrimaryStduent(stuId, name, chineseSocre, mathSocre, enrollmentDate, email,enrollmentStatus);
               students.add(primaryStduent);
           }
       }
       }
    }
    public Map<Integer,Integer> getScoreStatisticsBySubject(String subject){
        HashMap<Integer, Integer> scoreStatistics = new HashMap<>();
        try {
            for (Stduent student : students) {
                int score= (int) getScoreBySubject(student,subject);
                if(scoreStatistics.containsKey(score)){
                    scoreStatistics.put(score,scoreStatistics.get(score)+1);
                }else {
                    scoreStatistics.put(score,1);
                }
            }
        } catch (NullPointerException e) {
            System.out.println("处理学生成绩出错："+e.getMessage());
            e.fillInStackTrace();
        }
        return scoreStatistics;
    }
public Stduent findStudentWithHighestScore(String subject) {
    try {
        return Collections.max(students, new Comparator<Stduent>() {
            @Override
            public int compare(Stduent s1, Stduent s2) {
                return (int) (getScoreBySubject(s1, subject) - getScoreBySubject(s2, subject));
            }
        });
    } catch (NoSuchElementException e) {
        System.out.println("没有找到任何学生："+e.getMessage());
        e.fillInStackTrace();
        return null;//执行catch说明出问题，直接返回null
    }catch (ClassCastException e){
        System.out.println("学生的分数不可比较"+e.getMessage());
        e.fillInStackTrace();
        return null;
    }
}

    public Stduent findStudentWithLowestScore(String subject) {
        try {
            return Collections.min(students, new Comparator<Stduent>() {
                @Override
                public int compare(Stduent s1, Stduent s2) {
                    return (int) (getScoreBySubject(s1, subject) - getScoreBySubject(s2, subject));
                }
            });
        } catch (NoSuchElementException e) {
            System.out.println("没有找到任何学生："+e.getMessage());
            e.fillInStackTrace();
            return null;//执行catch说明出问题，直接返回null
        }catch (ClassCastException e){
            System.out.println("学生的分数不可比较"+e.getMessage());
            e.fillInStackTrace();
            return null;
        }
    }
    public void sortByTotalScore() {
        try {
            students.sort(new Comparator<Stduent>() {
                @Override
                public int compare(Stduent o1, Stduent o2) {
                    return (int) (o2.geTotalSocre() - o1.geTotalSocre());
                }


            });
        } catch (Exception e) {
            System.out.println("排序过程中出错:" + e.getMessage());
            e.printStackTrace();
        }
    }
    public Stduent updateStudentByIndex(int number, Stduent newStudent){
        try {
            if(number>=1&&number<=students.size()){
               return (Stduent) students.set(number-1,newStudent);
            }else {
                //System.out.println("不存在序号为:"+number+"学生信息");
               // return null;
                throw  new RuntimeException("序号超出范围："+number);
            }
        } catch (Exception e) {
            System.out.println("更新学生信息时出错："+e.getMessage());
            e.printStackTrace();
            return  null;
        }
    }
    public Stduent randomRollCall(){

        try {
            return  students.get(new Random().nextInt(students.size()));
        } catch (Exception e) {
            System.out.println( "随机点名出错："+e.getMessage());
            e.printStackTrace();
            return null;
        }
    }
    public void addStudent(Stduent s) {
        try {
            if (s != null && validateStudentEmail(s)) {
                students.add(s);
            }
        } catch (Exception e) {
            System.out.println("添加学生失败："+e.getMessage());
            e.printStackTrace();
        }

//        else {
//            System.out.println("学号" + s.getStuId() + "学号" + s.getName() + "邮箱" + s.getEmail() + "email of num error");
//        }
    }

    public boolean validateStudentEmail(Stduent stduent) {
        //1.健壮性判断，防空处理
        if (stduent == null || stduent.getEmail() == null) {
          throw  new NullPointerException("学生为空or邮箱为空");
        } else {
            return stduent.getEmail().matches("\\w+@\\w+\\.+\\w+");
        }
    }

    public void showAllStudnet(Collection students) {
        try {
            int i = 1;
            for (Object student : students) {
                System.out.println("第" + (i++) + "人" + student);
            }
        } catch (Exception e) {
            System.out.println("显示学生信息出错："+e.getMessage());
            e.printStackTrace();
        }
    }

    public void showAllStudnet() {
        showAllStudnet(students);
    }
    public Stduent findstudentBystuId(String stuId){
        for (Object student: students) {
            if(student instanceof Stduent stu&&stu.getStuId()==stuId){
                    return stu;
                }
        }
        return null;
    }
    public  double getAvergeScoreBySubject(String subject){
        try {
            double averge=0;
            for (Object stduent: students) {
                if (stduent instanceof Stduent stu) {
                    double scoreBySubject = getScoreBySubject(stu,subject);
                    averge += scoreBySubject;
                }
            }
            return  students.size()==0?0:averge/students.size();
        } catch (Exception e) {
            throw new RuntimeException("计算平时分时出错",e);
        }
    }

    private double getScoreBySubject(Stduent student, String subject) {
        try {
            switch (subject) {
                case "语文" -> {
                    return student.getChineseScore();
                }
                case "数学" -> {
                    return student.getMathScore();
                }
                case "历史" -> {
                    if (student instanceof MiddleStudent middleStudent) {
                        return middleStudent.getHistoryScore();
                    }
                }
                case "物理" -> {
                    if (student instanceof MiddleStudent middleStudent) {
                        return middleStudent.getPhysicsScore();
                    }
                }
            }
            return 0; //传递的subject不属于 语文,数学,历史,物理中的其中一种,直接返回0;
        } catch (Exception e) {
            throw new RuntimeException("获取当前学生"+student+"的"+subject+"时出错",e);
        }

    }
    public  Collection getStduentsEnrollmentdatesAfter(String date){
        Collection temps=new ArrayList();
        try {
            for (Object student : students) {
                if (student instanceof Stduent stu && stu.getEnrollmentdates()!=null){
                    if(stu.getEnrollmentdates().isAfter(LocalDate.parse(date))
                            || stu.getEnrollmentdates().isEqual(LocalDate.parse(date))){
                        temps.add(stu);
                    }
                }
            }
        }  catch (DateTimeParseException e) {
            System.out.println("解析"+date+"时出错"+e.getMessage());
            e.printStackTrace();
        }catch (Exception e){
            throw  new RuntimeException("获取指定入学日期值之后入学的学生出错：",e);
        }
        return  temps;
    }

    public  Collection getStduentsEnrollmentdatesBefore(String date){
        Collection temps=new ArrayList();
        try {
            for (Object student : students) {
                if (student instanceof Stduent stu && stu.getEnrollmentdates()!=null){
                    if(stu.getEnrollmentdates().isBefore(LocalDate.parse(date))
                            || stu.getEnrollmentdates().isEqual(LocalDate.parse(date))){
                        temps.add(stu);
                    }
                }
            }
        } catch (DateTimeParseException e) {
            System.out.println("解析"+date+"时出错"+e.getMessage());
            e.printStackTrace();
        }catch (Exception e){
            throw  new RuntimeException("获取指定入学日期值之前入学的学生出错：",e);
        }
        return  temps;
    }
    public boolean contains(Stduent stu) {
        try {
            return students.contains(stu);
        } catch (Exception e) {
            throw new RuntimeException(e);//将异常对象进一步封装将来可以打印出e的信息
        }
    }
    public Stduent findStudentById(String studentId) {
        try {
            for (Stduent student : students) {
                if (student.getStuId() .equals(studentId)) {
                    return student;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return null;//说明该学号的学生不存在
    }
    public void  uploadStudentAvatar(Stduent student, String localFilePath, String serverPath) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(localFilePath));
        //将上传图片进行名称的唯一性处理
        String filename = new File(localFilePath).getName();
        int index = filename.lastIndexOf(".");
        String extension = filename.substring( index);
        String newFilename=UUID.randomUUID().toString()+extension;
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(serverPath+"/"+newFilename));
                int b;
                 while((b=bis.read())!=-1){
                     bos.write(b);
                 }
                 bis.close();
                 bos.close();
        student.setAvatar(serverPath+"/"+newFilename);
    }

}
